﻿using NConf.ConfigSources;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;

namespace NConfTests
{
    
    
    /// <summary>
    ///This is a test class for JSONConfigSourceTest and is intended
    ///to contain all JSONConfigSourceTest Unit Tests
    ///</summary>
    [TestClass()]
    public class JSONConfigSourceTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes

        [ClassInitialize()]
        public static void MyClassInitialize(TestContext testContext)
        {
            // Create JSON config file.
            var sw = new StreamWriter("test.json");
            sw.WriteLine("{");
            sw.WriteLine("  \"General\": {");
            sw.WriteLine("    \"foo\": \"bar\",");
            sw.WriteLine("    \"other\": \"value\",");
            sw.WriteLine("    \"something\": {");
            sw.WriteLine("      \"test\": true");
            sw.WriteLine("    }");
            sw.WriteLine("  },");
            sw.WriteLine("  \"Second\": {");
            sw.WriteLine("    \"Section\": {");
            sw.WriteLine("      \"test\": 21");
            sw.WriteLine("    }");
            sw.WriteLine("  }");
            sw.WriteLine("}");
            sw.Close();

            // Create JSON config file with comments.
            sw = new StreamWriter("test-comments.json");
            sw.WriteLine("// A test config file with comments.");
            sw.WriteLine("{");
            sw.WriteLine("  \"General\": {");
            sw.WriteLine("    \"foo\": \"bar\",  // This sets foo to \"bar\"");
            sw.WriteLine("    \"other\": /* Comment in the middle of a line */ \"value\",");
            sw.WriteLine("    \"something\": {");
            sw.WriteLine("      \"test\": true");
            sw.WriteLine("    /**************");
            sw.WriteLine("     * Some sort of");
            sw.WriteLine("     * multi-line");
            sw.WriteLine("     * comment");
            sw.WriteLine("     */");
            sw.WriteLine("    }");
            sw.WriteLine("  },");
            sw.WriteLine("/* Commenting out older Second values");
            sw.WriteLine("  \"Second\": {");
            sw.WriteLine("    \"Section\": {");
            sw.WriteLine("      \"test\": 21");
            sw.WriteLine("    }");
            sw.WriteLine("  }");
            sw.WriteLine("*/");
            sw.WriteLine("  \"Second\": {");
            sw.WriteLine("    \"Section\": { /* Starting a comment after valid JSON on a line */");
            sw.WriteLine("      \"test\": 22");
            sw.WriteLine("    }");
            sw.WriteLine("  }");
            sw.WriteLine("/* Commenting out newer Second values");
            sw.WriteLine("  \"Second\": {");
            sw.WriteLine("    \"Section\": {");
            sw.WriteLine("      \"test\": 23");
            sw.WriteLine("    }");
            sw.WriteLine("  }");
            sw.WriteLine("*/");
            sw.WriteLine("}");
            sw.Close();

            // Create JSON config file with comment characters inside strings.
            sw = new StreamWriter("test-comment-chars-in-string.json");
            sw.WriteLine("// A test config file with comments.");
            sw.WriteLine("{");
            sw.WriteLine("  \"General\": {");
            sw.WriteLine("    \"fo//o\": \"bar\",  // This sets foo to \"bar\"");
            sw.WriteLine("    \"other\": /* Comment in the middle of a line */ \"http://value.org/\",");
            sw.WriteLine("    \"something\": {");
            sw.WriteLine("      \"test\": true");
            sw.WriteLine("    }");
            sw.WriteLine("  },");
            sw.WriteLine("/* Commenting out older Second values");
            sw.WriteLine("  \"Second\": {");
            sw.WriteLine("    \"Section\": {");
            sw.WriteLine("      \"test\": 21");
            sw.WriteLine("    }");
            sw.WriteLine("  }");
            sw.WriteLine("*/");
            sw.WriteLine("  \"Second\": {");
            sw.WriteLine("    \"Se*/ction\": { /* Starting a comment after valid JSON on a line */");
            sw.WriteLine("      \"te/* comment in a string; should stay in the string */st\": 22");
            sw.WriteLine("    }");
            sw.WriteLine("  }");
            sw.WriteLine("/* Commenting out newer Second values");
            sw.WriteLine("  \"Second\": {");
            sw.WriteLine("    \"Sec//tion\": {");
            sw.WriteLine("      \"te/*st\": 23");
            sw.WriteLine("    }");
            sw.WriteLine("  }");
            sw.WriteLine("*/");
            sw.WriteLine("}");
            sw.Close();
        } // end MyClassInitialize

        #endregion

        [TestMethod()]
        [DeploymentItem("NConf.dll")]
        public void ConstructorTest()
        {
            var source = new JSONConfigSource("test.json");
            dynamic key = source.GetConfigKey("General");
            Assert.AreEqual("bar", key.foo);
        } // end ConstructorTest()

        [TestMethod()]
        [DeploymentItem("NConf.dll")]
        public void KeysWithPeriodsTest()
        {
            var source = new JSONConfigSource("test.json");
            dynamic key = source.GetConfigKey("General");
            Assert.AreEqual(true, key.something.test);
        } // end KeysWithPeriodsTest()

        [TestMethod()]
        [DeploymentItem("NConf.dll")]
        public void SectionWithPeriodTest()
        {
            var source = new JSONConfigSource("test.json");
            dynamic key = source.GetConfigKey("Second.Section");
            Assert.AreEqual(21, key.test);
        } // end SectionWithPeriodTest()

        [TestMethod()]
        [DeploymentItem("NConf.dll")]
        public void SectionWithNestedValuesTest()
        {
            var source = new JSONConfigSource("test.json");
            dynamic key = source.GetConfigKey("Second");
            Assert.AreEqual(21, key.Section.test);
        } // end SectionWithNestedValuesTest()

        [TestMethod()]
        [DeploymentItem("NConf.dll")]
        public void CommentsTest()
        {
            var source = new JSONConfigSource("test-comments.json");
            dynamic key = source.GetConfigKey("General");
            Assert.AreEqual("bar", key.foo);
        } // end CommentsTest()

        [TestMethod()]
        [DeploymentItem("NConf.dll")]
        public void CommentsWithPeriodTest()
        {
            var source = new JSONConfigSource("test-comments.json");
            dynamic key = source.GetConfigKey("Second.Section");
            Assert.AreEqual(22, key.test);
        } // end CommentsWithPeriodTest()

        [TestMethod()]
        [DeploymentItem("NConf.dll")]
        public void CommentCharsInValueTest()
        {
            var source = new JSONConfigSource("test-comment-chars-in-string.json");
            dynamic key = source.GetConfigKey("General");
            Assert.AreEqual("http://value.org/", key.other);
        } // end CommentCharsInValueTest()

        [TestMethod()]
        [DeploymentItem("NConf.dll")]
        public void CommentCharsInKeyTest()
        {
            var source = new JSONConfigSource("test-comment-chars-in-string.json");
            dynamic key = source.GetConfigKey("Second.Se*/ction");
            Assert.AreEqual(22, key["te/* comment in a string; should stay in the string */st"]);
        } // end CommentCharsInKeyTest()
    } // end JSONConfigSourceTest
} // end NConfTests
